#include "SceneManager.h"
#include <iostream>

namespace GameEngine {
    SceneManager::SceneManager() : m_currentScene(nullptr) {}
    SceneManager::~SceneManager() {
        UnloadAllScenes();
    }

    void SceneManager::SwitchToScene(const std::string& name) {
        // 先停用并销毁当前场景
        if (m_currentScene) {
            m_currentScene->OnDeactivate();
            m_currentScene->OnDestroy();
            m_currentScene = nullptr;
        }

        auto it_factory = m_sceneFactories.find(name);
        if (it_factory == m_sceneFactories.end()) {
            throw std::runtime_error("SceneManager: No scene factory registered for '" + name + "'");
        }

        m_currentScene = it_factory->second();
        if (!m_currentScene) {
            throw std::runtime_error("SceneManager: Factory for '" + name + "' returned nullptr.");
        }

        m_currentSceneName = name;
        m_currentScene->m_isInitialized = true;
        m_currentScene->OnCreate();
        m_currentScene->m_isActive = true;
        m_currentScene->OnActivate();
        std::cout << "SceneManager: Switched to scene '" << name << "'" << std::endl;
    }

    void SceneManager::UpdateCurrentScene(float deltaTime) {
        if (m_currentScene && m_currentScene->IsActive()) {
            m_currentScene->Update(deltaTime);
        }
    }

    void SceneManager::RenderCurrentScene() {
        if (m_currentScene && m_currentScene->IsActive()) {
            m_currentScene->Render();
        }
    }

    std::shared_ptr<Scene> SceneManager::GetCurrentScene() const {
        return m_currentScene;
    }

    std::shared_ptr<Scene> SceneManager::GetScene(const std::string& name) {
        auto it = m_loadedScenes.find(name);
        if (it != m_loadedScenes.end()) {
            return it->second;
        }

        auto it_factory = m_sceneFactories.find(name);
        if (it_factory == m_sceneFactories.end()) {
            return nullptr;
        }

        auto scene = it_factory->second();
        m_loadedScenes[name] = scene;
        return scene;
    }

    void SceneManager::UnloadScene(const std::string& name) {
        auto it = m_loadedScenes.find(name);
        if (it != m_loadedScenes.end()) {
            if (m_currentScene == it->second) {
                m_currentScene->OnDeactivate();
                m_currentScene->OnDestroy();
                m_currentScene = nullptr;
            }
            m_loadedScenes.erase(it);
        }
    }

    void SceneManager::UnloadAllScenes() {
        if (m_currentScene) {
            m_currentScene->OnDeactivate();
            m_currentScene->OnDestroy();
            m_currentScene = nullptr;
        }
        m_loadedScenes.clear();
    }
}